package com.hdoit.ares.web.acc.wechat;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.github.binarywang.wxpay.bean.request.WxPayBaseRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.hdoit.ares.logical.acc.model.AccountInfo;
import com.hdoit.ares.logical.acc.model.GoldenBeanDetail;
import com.hdoit.ares.logical.acc.model.IncomeDetail;
import com.hdoit.ares.logical.acc.model.IncomeInfo;
import com.hdoit.ares.logical.acc.service.IAccountDetailService;
import com.hdoit.ares.logical.acc.service.IAccountInfoService;
import com.hdoit.ares.logical.acc.service.IGoldenBeanDetailService;
import com.hdoit.ares.logical.acc.service.IIncomeDetailService;
import com.hdoit.ares.logical.acc.service.IIncomeInfoService;
import com.hdoit.ares.logical.cust.model.Customer;
import com.hdoit.ares.logical.goods.model.GoodsInfo;
import com.hdoit.ares.logical.goods.service.IGoodsInfoService;
import com.hdoit.ares.logical.order.model.OrderGoods;
import com.hdoit.ares.logical.order.model.OrderInfo;
import com.hdoit.ares.logical.order.service.IOrderGoodsService;
import com.hdoit.ares.logical.order.service.IOrderInfoService;
import com.hdoit.ares.logical.viewmodel.goods.TempGoods;
import com.hdoit.ares.selfcommon.configurations.WechatConfiguration;
import com.hdoit.ares.selfcommon.configurations.model.WechatConfigModel;
import com.hdoit.ares.selfcommon.enums.AresManageContainer;
import com.tennetcn.common.logical.setting.model.ParamOption;
import com.tennetcn.common.logical.setting.service.IParamOptionService;
import com.tennetcn.common.message.WechatLoginModel;
import com.tennetcn.common.selfcommon.enums.wechat.WechatOrderStatus;
import com.tennetcn.common.utils.CommonUtils;
import com.tennetcn.common.utils.DateUtils;
import com.tennetcn.common.utils.JsonUtils;
import com.tennetcn.common.utils.RandomUtils;
import com.tennetcn.common.utils.StringHelper;
import com.tennetcn.component.wechat.BaseWechat;
import com.tennetcn.plugins.devshorts.enumerable.Enumerable;
import com.tennetcn.web.cbase.wechat.WechatPayService;

@Controller
@RequestMapping(value = "/wechat/acc/pay/")
public class PayWechat extends BaseWechat{

	@Override
	public String getRoutePath() {
		
		return "areas/wechat/acc/pay/";
	}
	 
	private WechatPayService wechatPayService;

	private IAccountInfoService accountInfoService;
	private IAccountDetailService accountDetailService;
	
	private IGoldenBeanDetailService goldenBeanDetailService;
	private IParamOptionService paramOptionService;
	
	private IIncomeInfoService incomeInfoService;
	private IIncomeDetailService incomeDetailService;
	
	private IGoodsInfoService goodsInfoService;
	private IOrderGoodsService orderGoodsService;
	private IOrderInfoService orderInfoService;
	

	public IAccountInfoService getAccountInfoService() {
		return accountInfoService;
	}
	@Resource
	public void setAccountInfoService(IAccountInfoService accountInfoService) {
		this.accountInfoService = accountInfoService;
	}

	public IAccountDetailService getAccountDetailService() {
		return accountDetailService;
	}
	@Resource
	public void setAccountDetailService(IAccountDetailService accountDetailService) {
		this.accountDetailService = accountDetailService;
	}

	public IGoldenBeanDetailService getGoldenBeanDetailService() {
		return goldenBeanDetailService;
	}
	@Resource
	public void setGoldenBeanDetailService(IGoldenBeanDetailService goldenBeanDetailService) {
		this.goldenBeanDetailService = goldenBeanDetailService;
	}

	public IParamOptionService getParamOptionService() {
		return paramOptionService;
	}
	@Resource
	public void setParamOptionService(IParamOptionService paramOptionService) {
		this.paramOptionService = paramOptionService;
	}
	
	public WechatPayService getWechatPayService() {
		return wechatPayService;
	}
	@Resource
	public void setWechatPayService(WechatPayService wechatPayService) {
		this.wechatPayService = wechatPayService;
	}

	
	public IIncomeInfoService getIncomeInfoService() {
		return incomeInfoService;
	}
	@Resource
	public void setIncomeInfoService(IIncomeInfoService incomeInfoService) {
		this.incomeInfoService = incomeInfoService;
	}
	public IIncomeDetailService getIncomeDetailService() {
		return incomeDetailService;
	}
	@Resource
	public void setIncomeDetailService(IIncomeDetailService incomeDetailService) {
		this.incomeDetailService = incomeDetailService;
	}
	
	
	/*@RequestMapping(value = payViewName, method = { RequestMethod.GET, RequestMethod.POST })
	public String pay(Model model) {
		// 等到 当前用户余额
		WechatLoginModel loginModel = wechatSession.getCurrentLogin();
		Customer customer = (Customer) loginModel.get(AresManageContainer.customer_account_info);

		AccountInfo accountInfo = new AccountInfo();
		accountInfo = accountInfoService.queryModelByCustomerId(customer.getId());

		Double allgolden = accountInfo.getGoldenBean();
		Double useBalance = accountInfo.getBalance();

		// 得到犹豫期金豆
		Double uselessgolden = 0.0;
		GoldenBeanDetail goldenBeanDetail = goldenBeanDetailService.queryGoldenInHesitate(customer
				.getId());
		if (goldenBeanDetail == null) {
			uselessgolden = 0.0;
		} else {
			uselessgolden = goldenBeanDetail.getSumgolden();
		}
		Double usegolden = allgolden - uselessgolden;

		// 等到 金豆 对 余额的 比例
		ParamOption paramOption = paramOptionService.queryModelByParamName("exchange");
		int exchangeRate = Integer.valueOf(paramOption.getParamValue());

		model.addAttribute("useBalance", useBalance);
		model.addAttribute("usegolden", usegolden);
		model.addAttribute("exchangeRate", exchangeRate);

		return view(payViewName);
	}*/
	

	public IGoodsInfoService getGoodsInfoService() {
		return goodsInfoService;
	}
	@Resource
	public void setGoodsInfoService(IGoodsInfoService goodsInfoService) {
		this.goodsInfoService = goodsInfoService;
	}
	public IOrderGoodsService getOrderGoodsService() {
		return orderGoodsService;
	}
	@Resource
	public void setOrderGoodsService(IOrderGoodsService orderGoodsService) {
		this.orderGoodsService = orderGoodsService;
	}
	public IOrderInfoService getOrderInfoService() {
		return orderInfoService;
	}
	@Resource
	public void setOrderInfoService(IOrderInfoService orderInfoService) {
		this.orderInfoService = orderInfoService;
	}

	private final String payViewName = "pay";
	private final String payInfoViewName = "payInfo";
	private final String paySuccessViewName = "paySuccess";
	
	
	

	
	/**
	 * 1.支付时创建订单
	 * 
	 */
	
	@ResponseBody
	@RequestMapping(value =payInfoViewName, method = { RequestMethod.POST },produces="text/plain;charset=utf-8")
	public String getPayInfoJson(String openId,String golgBean,String balance,String realPay, @RequestBody List<TempGoods> tempGoodsList) {
		Map<String,Object> resultMap=new HashMap<String, Object>();
		if(!checkTempGoodsList(tempGoodsList, resultMap)){
			return JsonUtils.toJson(resultMap);
		}		

		try {
			WxPayUnifiedOrderRequest request=getPayInfoRequest(openId);
			
			OrderInfo orderInfo=createOrderInfo();
			request.setOutTradeNo(orderInfo.getTradeNo());
			
			List<OrderGoods> orderGoodsList=getOrderGoods(orderInfo.getTradeNo(),tempGoodsList);
			if(orderGoodsList==null||orderGoodsList.size()==0){
				resultMap.put("result", "error");
				resultMap.put("message", "商品信息为空");
				return JsonUtils.toJson(resultMap);
			}
			TempOrderGoods og=getSumPrice(orderGoodsList, tempGoodsList);
			orderInfo.setTotalFee(og.getSumPrice());
			orderInfo.setName(og.getName());
			
			System.err.println("golgBean==="+Double.parseDouble(golgBean));
			System.err.println("balance==="+Double.parseDouble(balance));
			System.err.println("realPay==="+Double.parseDouble(realPay));
			System.err.println("all==="+og.getSumPrice());
			
			if((Double.parseDouble(golgBean)+Double.parseDouble(balance)+Double.parseDouble(realPay))==og.getSumPrice()){
				System.err.println("相等");
				//钱和金豆之间的兑换比例
				ParamOption paramOption = paramOptionService.queryModelByParamName("exchange");				
				int exchangeRate = Integer.valueOf(paramOption.getParamValue());
				
				orderInfo.setGoldBean(Double.parseDouble(golgBean)*exchangeRate);
				orderInfo.setIncome(Double.parseDouble(balance));
				orderInfo.setPayMoney(Double.parseDouble(realPay));	
			}else{
				System.err.println("不不不相等");
				resultMap.put("result", "error");
				resultMap.put("message", "金钱有误");
				return JsonUtils.toJson(resultMap);							
			}
			
			orderInfo = setCountForMoney(orderInfo);
			
			request.setTotalFee(WxPayBaseRequest.yuanToFee(String.valueOf(orderInfo.getPayMoney())));
			request.setBody(orderGoodsList.stream().findFirst().get().getName());
			
			
			
			orderInfo.setOpenId(request.getOpenid());
			orderInfo.setAttach(request.getAttach());
			
			
			orderInfo.setTimeStart(request.getTimeStart());
			orderInfo.setOrderStatus(WechatOrderStatus.paying);
			
			if(orderInfoService.addModel(orderInfo)){
				orderGoodsService.insertListEx(orderGoodsList);
			}
			resultMap.put("result", "success");
			if(Double.parseDouble(realPay)==0){
				resultMap.put("payInfo", null);
			}else{
				Map<String, String> payInfoMap = this.wechatPayService.getPayInfo(request);
				payInfoMap.put("tradeNo", orderInfo.getTradeNo());				
				String prepay_id=payInfoMap.get("package").replace("prepay_id=", "");
				orderInfo.setPrepayId(prepay_id);
				resultMap.put("payInfo", payInfoMap);
			}
			
		} catch (WxPayException e) {
			e.printStackTrace();
			resultMap.put("result", "error");
			resultMap.put("message", "构建订单逻辑出错");
		}
		
		return JsonUtils.toJson(resultMap);

	}
	
	private TempOrderGoods getSumPrice(List<OrderGoods> orderGoodsList, List<TempGoods> tempGoodsList) {
		double sumPrice=0.0;
		List<String> nameList=new ArrayList<String>();
		
		for (OrderGoods orderGoods:orderGoodsList) {
			TempGoods tempGoods=Enumerable.init(tempGoodsList).filter(gi->{return gi.getGoodsId().equals(orderGoods.getGoodsId());}).first();
			
			sumPrice+=orderGoods.getCount()*(orderGoods.getPrice());
			nameList.add(orderGoods.getName());
		}
		
		TempOrderGoods og=new TempOrderGoods();
		og.setName(StringHelper.join(nameList));
		og.setSumPrice(sumPrice);
		
		return og;
	}
	private List<OrderGoods> getOrderGoods(String orderId, List<TempGoods> tempGoodsList) {
		List<String> goodsIds=Enumerable.init(tempGoodsList).map(tempGoods->{return tempGoods.getGoodsId();}).toList();
		List<GoodsInfo> goodsInfos=goodsInfoService.queryListByIds(goodsIds);
		
		List<OrderGoods> orderGoodsList=new ArrayList<OrderGoods>();
		for (GoodsInfo goodsInfo : goodsInfos) {
			OrderGoods orderGoods=new OrderGoods();
			
			orderGoods.setId(CommonUtils.getKeyId());
			orderGoods.setGoodsId(goodsInfo.getId());
			orderGoods.setOrderId(orderId);
			orderGoods.setDescription(goodsInfo.getDescription());
			orderGoods.setName(goodsInfo.getName());
			
			orderGoods.setPrice(goodsInfo.getDealPrice());
			orderGoods.setType(goodsInfo.getType());
			orderGoods.setSubType(goodsInfo.getSubType());
			orderGoods.setGoodsMark(goodsInfo.getGoodsMark());
			
			int count=Enumerable.init(tempGoodsList).filter(tempGoods->goodsInfo.getId().equals(tempGoods.getGoodsId())).first().getCounts();
			orderGoods.setCount(count);
			
			orderGoodsList.add(orderGoods);
		}
		return orderGoodsList;	
	}
	//判断购买商品是否符合构建订单的逻辑
	private boolean checkTempGoodsList(List<TempGoods> tempGoodsList, Map<String, Object> resultMap) {
		if (tempGoodsList == null) {
			resultMap.put("result", "error");
			resultMap.put("message", "商品信息为空");
			return false;
		}
		for (int i = 0; i < tempGoodsList.size(); i++) {
			TempGoods tempGoods = tempGoodsList.get(i);
			if (StringUtils.isEmpty(tempGoods.getGoodsId()) || StringUtils.isEmpty(tempGoods.getCounts())) {
				resultMap.put("result", "error");
				resultMap.put("message", "商品或数量不能为空");
				return false;
			}
		}
		return true;
	}
	

	private WxPayUnifiedOrderRequest getPayInfoRequest(String openId){
		WxPayUnifiedOrderRequest request=new WxPayUnifiedOrderRequest();
		WechatConfigModel wcm=getWechatConfigModel();
		request.setAppid(wcm.getAppId());
		request.setMchId(wcm.getMchId());
		request.setSpbillCreateIp(wcm.getSpbillCreateIp());
		request.setNotifyURL(wcm.getNotifyURL());
		request.setTradeType(wcm.getTradeType());
		request.setOpenid(openId);
		request.setTimeStart(DateUtils.convertDate2String("yyyyMMddHHmmss", new Date()));
		
		return request;
	}
	
	
	private WechatConfigModel getWechatConfigModel(){
		return WechatConfiguration.getInstance().wechatConfigModel;
	}
	
	private OrderInfo createOrderInfo(){
		WechatConfigModel wcm=getWechatConfigModel();
		OrderInfo orderInfo=new OrderInfo();
		orderInfo.setAppId(wcm.getAppId());
		orderInfo.setTradeNo(getTradeNo(wcm.getOrgCode()));
		orderInfo.setMchId(wcm.getMchId());
		orderInfo.setTradeType(wcm.getTradeType());
		
		return orderInfo;
	}
	
	//生成流水号
	private String getTradeNo(String orgCode){
		return orgCode+DateUtils.convertDate2String("yyyyMMddHHmmssSSS", new Date())+RandomUtils.randomNumbers(6);
	}
	
	
	//提取出来用于计算一笔订单金豆数、奖金数和现金数需要支付的数目
	public OrderInfo setCountForMoney(OrderInfo orderInfo){
		//需要支付的金豆数、奖金数和微信需要支付的金额（此时就需要知道该用户可用金豆和可用现金的总数）
		WechatLoginModel loginModel = wechatSession.getCurrentLogin();
		Customer customer = (Customer) loginModel.get(AresManageContainer.customer_account_info);
		//可用金豆
		double useGoldBean = (double) getGoldBean(customer.getId()).get("useGoldBean");		
		//得到余额
		Double useBalance = accountInfoService.queryModelByCustomerId(customer.getId()).getBalance();
		//总金额
		double totalFee = orderInfo.getTotalFee();
		
		//可用奖金
		/*double useIncome =  (double) getIncome(customer.getId()).get("useIncome");*/
		
		Boolean change = false;
		
		//比较orderInfo中数据与实际可用数据比较
		if(useGoldBean<orderInfo.getGoldBean()){
			if(useGoldBean>0){
				orderInfo.setGoldBean(useGoldBean);
			}else{
				orderInfo.setGoldBean(0);
			}
			change = true;
		}
		if(useBalance<orderInfo.getIncome()){
			if(useBalance>0){
				orderInfo.setIncome(useBalance);
			}else{
				orderInfo.setIncome(0);
			}
			change = true;
		}
		if(change){
			//钱和金豆之间的兑换比例
			ParamOption paramOption = paramOptionService.queryModelByParamName("exchange");
			int exchangeRate = Integer.valueOf(paramOption.getParamValue());
			orderInfo.setPayMoney(totalFee-orderInfo.getGoldBean()/exchangeRate-orderInfo.getIncome());
		}
		
		return orderInfo;		
	}
	
	
	/*@ResponseBody
	@RequestMapping(value = payInfoViewName, method = { RequestMethod.POST }, produces = "text/plain;charset=utf-8")
	public String getPayInfoJson(HttpServletRequest req, String openId,double money) {
	必填字段 [body, outTradeNo, totalFee, spbillCreateIp] 必须提供值 
		WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
		request.setOutTradeNo("" + System.currentTimeMillis()
				+ RandomUtils.randomInt(1000, 9999));
		request.setTotalFee(WxPayBaseRequest.yuanToFee(String.valueOf(money)));
		request.setSpbillCreateIp("123.207.34.17");
		request.setBody("");
		request.setOpenid(openId);

		Map<String, String> payInfoMap = null;
		try {
			payInfoMap = wechatPayService.getPayInfo(request);

			payInfoMap.put("outTradeNo", request.getOutTradeNo());
		} catch (WxPayException e) {
			e.printStackTrace();
		}
		payInfoMap.get("package").replace("prepay_id=", "");

		return JsonUtils.toJson(payInfoMap);

	}
	*/
	

	

	@RequestMapping(value = paySuccessViewName, method = { RequestMethod.GET,RequestMethod.POST },produces = "text/plain;charset=utf-8")
	@ResponseBody
	public void paySuccess(Model model,String orderInfoId) {
		WechatLoginModel loginModel = wechatSession.getCurrentLogin();
		model.addAttribute("loginModel", loginModel);
		Customer customer = (Customer) loginModel.get(AresManageContainer.customer_account_info);
		model.addAttribute("customer", customer);
		//查出订单改变订单的支付状态
		orderInfoService.applyChangeState(orderInfoId);
		//生成各种明细
	    orderInfoService.addPayInfo(orderInfoId,customer.getId());	
	}
	
	@RequestMapping(value = payViewName, method = { RequestMethod.GET, RequestMethod.POST })
	public String pay(Model model) {
		// 等到 当前用户余额
		WechatLoginModel loginModel = wechatSession.getCurrentLogin();
		Customer customer = (Customer) loginModel.get(AresManageContainer.customer_account_info);

		AccountInfo accountInfo = new AccountInfo();
		accountInfo = accountInfoService.queryModelByCustomerId(customer.getId());

		Double allgolden = accountInfo.getGoldenBean();
		Double useBalance = accountInfo.getBalance();

		// 得到犹豫期金豆
		Double uselessgolden = 0.0;
		GoldenBeanDetail goldenBeanDetail = goldenBeanDetailService.queryGoldenInHesitate(customer
				.getId());
		if (goldenBeanDetail == null) {
			uselessgolden = 0.0;
		} else {
			uselessgolden = goldenBeanDetail.getSumgolden();
		}
		Double usegolden = allgolden - uselessgolden;

		// 等到 金豆 对 余额的 比例
		ParamOption paramOption = paramOptionService.queryModelByParamName("exchange");
		int exchangeRate = Integer.valueOf(paramOption.getParamValue());

		model.addAttribute("useBalance", useBalance);
		model.addAttribute("usegolden", usegolden);
		model.addAttribute("exchangeRate", exchangeRate);
		model.addAttribute("customer", customer);

		return view(payViewName);
	}
	
	/**
	 *考虑到以下几种情况：
	 *1.只付了金豆
	 *2.只付了奖金
	 *3.只付了现金
	 *4.只付了金豆和奖金
	 *5.只付了金豆和现金
	 *6.支付了奖金和现金
	 *7.金豆、奖金和现金一起支付
	 *考虑到支付现金和不支付现金的情况又有不同：
	 *因此应该这样考虑：
	 *支付现金的情况：3、5、6、7
	 *不支付现金的情况：1、2、4
	 *
	 */
	/*@RequestMapping(value = payViewName, method = { RequestMethod.GET, RequestMethod.POST })
	public String pay(Model model,double goldBean,double income,double payMoney) {
		
		WechatLoginModel loginModel = wechatSession.getCurrentLogin();
		Customer customer = (Customer) loginModel.get(AresManageContainer.customer_account_info);
        
		
		
		
		return view(payViewName);
	}*/
	
	/**
	 * 将得到当前用户可用金豆，可用奖金的方法提取出来
	 * @param id
	 * @return
	 */
	
	    //用于提取查询可用金豆和不可用金豆的公共方法
		public HashMap<String,Object> getGoldBean(String id){
			HashMap<String,Object> map = new HashMap<String,Object>();
			
			AccountInfo accountInfo  = accountInfoService.queryModelByCustomerId(id);
			
			Double allGoldBean = accountInfo.getGoldenBean();

			// 得到犹豫期余额
			Double uselessGoldBean = 0.0;
			GoldenBeanDetail goldenBeanDetail = goldenBeanDetailService.queryGoldenInHesitate(id);
			if (goldenBeanDetail == null) {
				uselessGoldBean = 0.0;
			} else {
				uselessGoldBean = goldenBeanDetail.getSumgolden();
			}
			Double useGoldBean = allGoldBean - uselessGoldBean;
			map.put("uselessGoldBean", uselessGoldBean);
			map.put("useGoldBean", useGoldBean);
			
			return map;
		}
		
		
		//用于提取查询可用奖金和不可用奖金的公共方法
		public HashMap<String,Object> getIncome(String id){

			IncomeInfo incomeInfo = new IncomeInfo();
			incomeInfo = incomeInfoService.queryIncomeInfo(id);

			Double allIncome = incomeInfo.getIncomeBalance();

			// 得到犹豫期余额
			Double uselessIncome = 0.0;
			IncomeDetail incomeDetail = incomeDetailService.queryIncomeInHesitate(id);
			if (incomeDetail == null) {
				uselessIncome = 0.0;
			} else {
				uselessIncome = incomeDetail.getSumincome();
			}
			Double useIncome = allIncome - uselessIncome;
			
			HashMap<String, Object> res = new HashMap<String, Object>();
			res.put("useIncome", useIncome);
			res.put("uselessIncome", uselessIncome);
			return res;
		}
	
		
		
		class TempOrderGoods{
			private double sumPrice;
			
			private String name;

			public double getSumPrice() {
				return sumPrice;
			}

			public void setSumPrice(double sumPrice) {
				this.sumPrice = sumPrice;
			}

			public String getName() {
				return name;
			}

			public void setName(String name) {
				this.name = name;
			}
		}
}
